Load required libraries

library(tidyverse)
── Attaching core tidyverse packages ───────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.2     ✔ tibble    3.2.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     
── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(here)
G3;here() starts at /Users/peter.macpherson/Library/Mobile Documents/com~apple~CloudDocs/Documents/Documents - Peter’s Mac mini/Projects/AQ-MTB_2025-05-14/Work/Data/aq_mtb
g
library(brms)
G3;Loading required package: Rcpp
gG3;Loading 'brms' package (version 2.22.0). Useful instructions
can be found by typing help('brms'). A more detailed introduction
to the package is available through vignette('brms_overview').
gG3;
Attaching package: ‘brms’

gG3;The following object is masked from ‘package:stats’:

    ar

g
library(tidybayes)
G3;
Attaching package: ‘tidybayes’

gG3;The following objects are masked from ‘package:brms’:

    dstudent_t, pstudent_t, qstudent_t, rstudent_t

g
library(sf)
G3;Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
g
library(mgcv)
G3;Loading required package: nlme
gG3;
Attaching package: ‘nlme’

gG3;The following object is masked from ‘package:dplyr’:

    collapse

gG3;This is mgcv 1.9-3. For overview type 'help("mgcv-package")'.
gG3;
Attaching package: ‘mgcv’

gG3;The following objects are masked from ‘package:brms’:

    s, t2

g
library(priorsense)
library(osmdata)
G3;Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright
g
library(nngeo) 
G3;Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
g

Import the modelling dataset - cleaned and prepped in the 2025-05-12_aq_clean.Rmd script


aq_model_data <- read_rds("input_data/aq_model_data.rds")

#also load the scale clusters
load("input_data/scale_72_clusters.rda") #SCALE clusters

#and the grid data
read_rds("input_data/mw_100m_cropped.rds")
$mwi_ppp_2020.tif
               [,1]         [,2]         [,3]         [,4]         [,5]         [,6]         [,7]         [,8]         [,9]        [,10]
  [1,]  0.045165006  0.046947237  0.055178735  0.047102101  0.043815471  0.041929662  0.039621390   0.03764743 3.824615e-02 3.529998e-02
  [2,]  0.054517046  0.047781128  0.052100033  0.046856463  0.042057369  0.028544975  0.027005022   0.02849834 2.889967e-02 2.749119e-02
  [3,]  0.045086842  0.047777772  0.041951492  0.034255959  0.029440563  0.024227845  0.016665278   0.02430716 7.012391e-03 1.374129e-02
  [4,]  0.035714723  0.039766397  0.035008151  0.032815386  0.030017985  0.028784296  0.029581040   0.02444118 1.111266e-02 4.598498e-03
  [5,]  0.015322668  0.018739052  0.018032806  0.018089430  0.017559310  0.018649841  0.017364351   0.01674390 1.384361e-02 5.014876e-03
              [,11]        [,12]        [,13]        [,14]        [,15]        [,16]        [,17]        [,18]        [,19]        [,20]
  [1,] 3.581402e-02  0.033903446  0.028697260  0.025856392 9.365267e-03 4.969447e-03 4.880766e-03 6.018387e-03 7.693967e-03 1.687009e-02
  [2,] 3.080107e-02  0.031454172  0.036637034  0.028348375 1.773694e-02 5.785842e-03 6.604420e-03 6.460932e-03 8.471724e-03 1.088048e-02
  [3,] 2.850383e-02  0.033486295  0.035977926  0.021789778 7.277420e-03 5.582869e-03 6.420635e-03 6.296951e-03 8.607163e-03 7.565869e-03
  [4,] 4.251544e-03  0.014496404  0.024309691  0.025809046 5.967221e-03 5.781442e-03 5.793448e-03 8.620093e-03 8.066839e-03 7.239441e-03
  [5,] 3.449674e-03  0.004229320  0.027064180  0.021735243 2.350955e-02 6.558061e-03 5.777395e-03 6.241026e-03 6.318555e-03 7.906212e-03
              [,21]        [,22]        [,23]        [,24]        [,25]        [,26]        [,27]        [,28]        [,29]        [,30]
  [1,] 7.483703e-03 1.134669e-02 2.477654e-02 1.747209e-02   0.02301022   0.03323989   0.03443765   0.04373282   0.03239537   0.03268054
  [2,] 6.492021e-03 1.798505e-02 3.820698e-02 3.622469e-02   0.04873810   0.06264146   0.04502079   0.04902079   0.03930074   0.04743655
  [3,] 1.413537e-02 2.868031e-02 4.856283e-02 7.635828e-02   0.10526711   0.10480442   0.09942765   0.08063150   0.07026784   0.07916132
  [4,] 3.765117e-02 4.892825e-02 8.083706e-02 6.265849e-02   0.06352694   0.10991651   0.11036292   0.10957718   0.09102185   0.09063222
  [5,] 4.181869e-02 6.396030e-02 6.208089e-02 5.934627e-02   0.06683331   0.11021938   0.11196631   0.10069560   0.08459925   0.09193873
              [,31]        [,32]        [,33]        [,34]        [,35]        [,36]        [,37]        [,38]        [,39]        [,40]
  [1,]   0.01216105 6.328823e-03   0.01512775   0.02006114 3.101150e-02   0.05473484   0.06160709   0.07647948   0.07574075   0.07371373
  [2,]   0.04709647 1.577023e-02   0.01547693   0.01512168 9.752575e-03   0.03868737   0.05658274   0.06831920   0.07236640   0.06479138
  [3,]   0.08027354 4.902577e-02   0.04347426   0.04361450 2.506110e-02   0.02168380   0.03363772   0.07003722   0.10318663   0.07466165
  [4,]   0.10364193 1.078961e-01   0.06888389   0.06897457 7.109120e-02   0.06687172   0.04877206   0.06761945   0.06558794   0.05342549
  [5,]   0.10197861 1.167887e-01   0.11340023   0.07957450 8.267088e-02   0.07813363   0.05316366   0.03048283   0.04607106   0.05050959
             [,41]       [,42]       [,43]        [,44]        [,45]        [,46]        [,47]        [,48]        [,49]        [,50]
  [1,]  0.09937067  0.09119225  0.08600094   0.09103850   0.09306126   0.17105776   0.16657399   0.19017223   0.18780756   0.25865054
  [2,]  0.08613592  0.09276834  0.08768278   0.09463739   0.09931904   0.20142318   0.34862801   0.24239205   0.20016080   0.14733949
  [3,]  0.08796223  0.08529528  0.05861057   0.08760586   0.17597923   0.18829565   0.30547777   0.18160681   0.10488693   0.05029128
  [4,]  0.07356653  0.04595139  0.06095412   0.07659898   0.20957065   0.22002560   0.26929030   0.13957511   0.13037296   0.12920222
  [5,]  0.05924074  0.12837498  0.10924210   0.04965207   0.03692738   0.13063972   0.13985389   0.22550066   0.22139461   0.23821150
              [,51]        [,52]        [,53]        [,54]        [,55]        [,56]        [,57]        [,58]        [,59]        [,60]
  [1,]   0.18521543 1.718710e-01   0.17261122 1.592420e-01   0.13821790 2.070713e-01 2.180091e-01 2.510735e-01 3.347855e-01   0.42194489
  [2,]   0.25576282 1.704141e-01   0.16087675 6.019334e-02   0.05911760 2.086819e-01 2.241761e-01 2.393655e-01 2.442953e-01   0.28544879
  [3,]   0.08434317 1.395781e-01   0.03054703 2.303165e-02   0.02988590 1.481759e-01 1.958029e-01 2.119675e-01 2.289245e-01   0.22243160
  [4,]   0.12479196 1.226818e-01   0.12564214 1.318173e-01   0.13020913 1.327822e-01 2.432093e-01 2.560078e-01 2.778168e-01   0.30719724
  [5,]   0.22799887 1.374678e-01   0.14205216 1.374896e-01   0.14270458 2.208541e-01 2.599400e-01 2.764551e-01 4.585261e-01   0.61238015
              [,61]       [,62]        [,63]       [,64]        [,65]       [,66]       [,67]       [,68]       [,69]       [,70]       [,71]
  [1,]   0.20092252   0.2094545   0.23813984   0.2600536   0.28496569   0.3515317   0.3495567   3.0187855   3.4292254   4.3702903  10.2430563
  [2,]   0.37174022   0.2000832   0.20835581   0.2420900   0.25386712   0.3162111   0.3505953   2.8476219   2.6364815   3.5290518   4.9171147
  [3,]   0.31947485   0.3825941   0.37987089   0.2292890   0.24251479   0.2557049   2.4554725   2.3886611   1.5429624   2.8309567   3.7996442
  [4,]   0.34511879   0.5266556   0.32725015   0.2879633   0.32016167   0.8491008   2.2822711   3.1561983   4.8729448   4.3276281   5.2610259
  [5,]   1.26680827   1.3391285   1.04976392   0.3362455   0.29695830   0.2514963   0.7431583   6.0843654   6.2483072   5.5046158   5.5970216
             [,72]       [,73]       [,74]       [,75]       [,76]       [,77]       [,78]       [,79]       [,80]       [,81]       [,82]
  [1,]  12.3174086  20.4170475   5.9770074   5.8101201   6.1680431   7.0288363   2.9920485   2.7822750   3.2919111   2.7028601   2.7344890
  [2,]  11.4855623   3.7609022   3.5631394   2.8713186   2.5883286   6.6772809   6.6999898   6.8617449   3.1268249   2.7026587   2.1398206
  [3,]   4.0249171   2.3710566   2.3969679   1.5280255   1.3292254   1.3552140   6.3890018   6.8920774   5.9485264   6.3546324   2.1996837
  [4,]   1.3237036   1.1526742   2.2051387   1.6958532   5.7821097   1.2228683   2.1854522   6.9267850   5.9227381   5.7966475   2.1904876
  [5,]   1.9726193   1.2746783   1.6196227   1.4951222   5.7002840   1.2784475   5.3949475   2.2073100   2.0879290   2.0115442   1.1903656
             [,83]       [,84]       [,85]       [,86]       [,87]       [,88]       [,89]       [,90]       [,91]       [,92]       [,93]
  [1,]   2.8262646   3.1302779   3.6975005   2.1694636   2.2199211   2.3952386   2.0133886   1.0360730   6.0406532   6.6095033   6.3419876
  [2,]   1.7706543   1.8591148   2.6041703   1.9700989   2.0043545   2.1224627  12.0202541  10.6813793   5.7113476   5.8507247   5.5529652
  [3,]   0.7009542   0.5428279   1.0550138   0.9149451   9.6139355  10.1034241   9.7381792   7.6451182   5.3572125   5.1382504   5.1880946
  [4,]   0.6239597   0.5024059   0.9726501   0.9038598   9.6681395   7.2640862   6.9079909   5.7228518   6.3007116   6.8418317   7.1582618
  [5,]   0.4369978   0.4899155   0.8078130   0.7381263   8.1139145   6.2780352   5.4850063   5.4929547   6.6182308   8.1480541   7.9830341
            [,94]      [,95]      [,96]      [,97]      [,98]      [,99]     [,100]     [,101]     [,102]     [,103]     [,104]      [,105]
  [1,]  6.0880580  4.9141769  5.6921430  5.6045480  5.6583200  5.7986665  4.8305206  4.5144963  4.3507361  4.8232894  4.1951013   4.6705604
  [2,]  5.3891821  5.2441683  4.3157148  4.7750669  4.9417787  5.7972479  5.7227149  6.0235286  5.1872697  5.3412123  5.1507735   4.7766061
  [3,]  5.2370167  5.1144838  4.4092488  4.2801752  4.8011594  5.8726711  5.7670879  6.0404143  6.7926741  6.6716657  5.2236753   5.0849514
  [4,]  7.2552085  6.9078765  5.8223286  5.2468567  5.3122015  6.6020727  6.6301870  6.3754029  7.2572618  7.1930847  7.2747545   7.0348992
  [5,]  7.6431541  7.6273088  6.5719180  5.9137011  5.9537210  6.5491629  6.6482563  6.1040545  6.8009992  7.0888548  7.2325339   6.9409246
            [,106]      [,107]      [,108]      [,109]      [,110]      [,111]      [,112]      [,113]      [,114]      [,115]      [,116]
  [1,]   4.0513868   4.5824718  31.0151443  35.9615288  31.9965153  33.5947914  34.8950462  33.6029587  32.1246338  31.0912933  13.1747513
  [2,]   4.3982000   4.5165482  30.4003181  31.6037254  30.7493134  31.7781143  35.9739647  37.8679657  37.2548790  15.6511335  14.6784821
  [3,]   5.1197200   4.4855256  33.6331902  39.4704590  25.6988716  33.0550232  13.5869970  13.1186905  13.0235996  13.0852079  16.8719463
  [4,]   7.5529518   6.8021359  38.6025314  38.8714218  16.4733143  13.1496153  11.0804739   9.1725912  11.2854414  11.4492359  14.8278837
  [5,]   7.0277257   7.7998891   6.9491796  14.6560345  17.5421658  16.1886940  11.8365650  11.4074469  13.3405104  13.5668907  14.1344957
            [,117]      [,118]      [,119]      [,120]      [,121]      [,122]      [,123]      [,124]      [,125]      [,126]      [,127]
  [1,]  17.4172173  14.5559740  10.0551395   0.9203696   0.4967222   0.4107275   0.3978702   0.4675624   0.7120231   0.5725706   0.5796408
  [2,]  16.7342072  11.8646288  11.6098852   0.8615871   0.6930147   0.6287227   0.4980069   0.7469794   0.5880303   0.4945861   0.4778275
  [3,]  17.6651497  16.5033340  14.2913799   1.1762685   1.0414619   0.9750723   0.9179240   0.6648465   0.6006990   0.4671351   0.4315493
  [4,]  15.0737171  14.5026913   1.4341162   1.7666528   1.2385327   1.2163831   1.1903278   1.0431690   0.6815187   0.6674115   0.6116236
  [5,]  14.0739212   0.9036093   1.0228646   1.7256023   1.1906258   1.1074116   1.0897969   0.8469090   0.8302435   0.7722517   0.7019941
            [,128]      [,129]      [,130]     [,131]     [,132]     [,133]     [,134]     [,135]     [,136]     [,137]     [,138]     [,139]
  [1,]   0.5407016   5.6824121   5.5070438   5.393878   5.314744   5.378588   5.516953   5.472218   6.871101   7.120472   2.490248   1.913114
  [2,]   0.4782741   0.5772134   5.7760925   5.619320   5.583245   5.598059   5.671175   6.422924   7.114538   6.954295   2.615454   2.365523
  [3,]   0.4778309   6.0533495   5.8488727   5.827873   5.702469   5.692585   2.055359   2.058331   2.605898   2.534510   2.526598   1.925066
  [4,]   6.0364213   6.8703146   6.9667211   6.728249   2.507176   2.410894   2.355129   2.363863   2.335734   2.941173   2.280494   2.165629
  [5,]   7.4033751   6.2904220   6.0554729   5.708776   2.480082   2.428432   2.440901   2.502323   2.452162   2.456221   2.371370   2.334642
           [,140]     [,141]     [,142]     [,143]     [,144]     [,145]     [,146]     [,147]     [,148]     [,149]     [,150]      [,151]
  [1,]   1.890159   1.864571   1.824639   1.813932   1.855493   1.862693   1.844257   1.884519   1.856309   1.911597   1.900523   1.8835605
  [2,]   1.930770   1.902335   1.879635   1.835053   1.837441   1.848145   1.740682   1.844983   1.900461   1.933071   1.847667   1.8871386
  [3,]   1.854827   1.917260   1.922128   1.888102   1.913544   1.864133   1.771954   1.868454   1.890933   1.831353   1.933270   1.9211165
  [4,]   2.187655   2.135860   2.126067   2.083079   2.073362   2.087825   2.053761   2.042283   2.012455   2.036653   2.052104   1.9967043
  [5,]   2.811734   2.288969   2.239703   2.176805   2.207034   2.119645   2.070684   2.082571   1.989093   2.088601   2.078266   2.0321856
            [,152]      [,153]      [,154]      [,155]     [,156]     [,157]     [,158]     [,159]     [,160]      [,161]      [,162]     [,163]
  [1,]   1.8760191   4.2506528   1.8467858   1.9328438   4.556878   4.581502   5.842960   5.753704   4.339655   5.3159437   3.6693192  3.5465922
  [2,]   1.8791692   4.2897072   4.4196887   4.4844222   4.750791   5.543705   5.940609   5.749850   4.410793   5.4709144   5.1160870  3.6569257
  [3,]   1.8962737   4.3825073   4.1637969   4.6726365   4.731542   4.696297   5.871382   5.844340   4.788056   5.8306942   3.9437084  3.8018162
  [4,]   2.6364172   2.5760887   4.5244684   4.6207194   5.156001   5.343033   5.413106   5.551797   5.356392   3.1116621   3.1301842  3.1519930
  [5,]   2.6615610   2.5835884   2.7367139   2.7678025   5.207396   5.004921   4.730000   4.490225   6.635791   3.2056251   3.5913785  3.6644924
           [,164]     [,165]     [,166]     [,167]     [,168]     [,169]    [,170]    [,171]    [,172]    [,173]    [,174]    [,175]     [,176]
  [1,]  3.4214435  3.2192101  3.0704648  3.2135775  4.2359557  4.4121046  4.179620  5.511585  7.292460  4.900838  4.766211  4.537093  3.3284004
  [2,]  3.6246648  3.5184062  3.2872734  3.1027408  4.3657980  5.0197420  6.747860  8.048831  7.825340  7.773330  4.906329  4.761338  3.9066331
  [3,]  3.5798521  3.6366291  3.9564095  5.8185658  6.5702181  6.7610564  6.643492  7.909804  7.872230  8.015193  5.043985  5.217367  6.0537314
  [4,]  2.3774395  3.6038818  3.4744658  4.0604777  4.2596602  4.2969036  4.415190  5.865735  7.650286  7.599905  7.653657  5.146161  5.9680948
  [5,]  3.3508301  3.3644121  3.6195219  4.1825180  4.3101077  4.4454837  5.979053  9.620084 15.794232 10.375804  9.111597  5.311432  5.9213576
           [,177]
  [1,]  3.8432529
  [2,]  9.6162081
  [3,] 11.1199265
  [4,] 11.5795832
  [5,] 11.8466797
 [ reached 'max' / getOption("max.print") -- omitted 172 rows ]

attr(,"dimensions")
$x
$from
[1] 2755

$to
[1] 2931

$offset
[1] 32.67125

$delta
[1] 0.0008333333

$refsys
Coordinate Reference System:
  User input: WGS 84 
  wkt:
GEOGCRS["WGS 84",
    ENSEMBLE["World Geodetic System 1984 ensemble",
        MEMBER["World Geodetic System 1984 (Transit)"],
        MEMBER["World Geodetic System 1984 (G730)"],
        MEMBER["World Geodetic System 1984 (G873)"],
        MEMBER["World Geodetic System 1984 (G1150)"],
        MEMBER["World Geodetic System 1984 (G1674)"],
        MEMBER["World Geodetic System 1984 (G1762)"],
        MEMBER["World Geodetic System 1984 (G2139)"],
        MEMBER["World Geodetic System 1984 (G2296)"],
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]],
        ENSEMBLEACCURACY[2.0]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    USAGE[
        SCOPE["Horizontal component of 3D system."],
        AREA["World."],
        BBOX[-90,-180,90,180]],
    ID["EPSG",4326]]

$point
[1] FALSE

$values
NULL

attr(,"class")
[1] "dimension"

$y
$from
[1] 7627

$to
[1] 7803

$offset
[1] -9.363749

$delta
[1] -0.0008333333

$refsys
Coordinate Reference System:
  User input: WGS 84 
  wkt:
GEOGCRS["WGS 84",
    ENSEMBLE["World Geodetic System 1984 ensemble",
        MEMBER["World Geodetic System 1984 (Transit)"],
        MEMBER["World Geodetic System 1984 (G730)"],
        MEMBER["World Geodetic System 1984 (G873)"],
        MEMBER["World Geodetic System 1984 (G1150)"],
        MEMBER["World Geodetic System 1984 (G1674)"],
        MEMBER["World Geodetic System 1984 (G1762)"],
        MEMBER["World Geodetic System 1984 (G2139)"],
        MEMBER["World Geodetic System 1984 (G2296)"],
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]],
        ENSEMBLEACCURACY[2.0]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    USAGE[
        SCOPE["Horizontal component of 3D system."],
        AREA["World."],
        BBOX[-90,-180,90,180]],
    ID["EPSG",4326]]

$point
[1] FALSE

$values
NULL

attr(,"class")
[1] "dimension"

attr(,"raster")
$affine
[1] 0 0

$dimensions
[1] "x" "y"

$curvilinear
[1] FALSE

$blocksizes
        x y
[1,] 3892 1

attr(,"class")
[1] "stars_raster"
attr(,"class")
[1] "dimensions"
attr(,"class")
[1] "stars"

Model 1:

“We fitted a spatially smooth regression model for log-transformed PM2.5 concentrations using a Gaussian process (GP) smooth over spatial coordinates (x, y) to capture flexible spatial trends. Seasonal variation was modelled using a Fourier series expansion of day-of-year up to the 3rd harmonic (i.e., sine and cosine terms for annual, semi-annual, and tri-annual cycles) to account for complex seasonal patterns. The model was fitted in a Bayesian framework using brms with a Gaussian likelihood and the cmdstanr backend.”

Note, priors are still causing issues for me, so we will comment out now, and use the defauly stan weakly informative priors

Priors


priors <- c(
  prior(normal(3.4, 1), class = "Intercept"),
  prior(normal(0,1), class = "b"),
  prior(exponential(1), class = "sigma"),
  prior(exponential(1), class = "sdgp"),
  prior(normal(0, 1), class = "lscale", lb = 0)
)

Fit prior only model

Now model with data.

pp_check(m1)
G3;Using 10 posterior draws for ppc type 'dens_overlay' by default.
g

Compare prior-only model to model with data using priorsense package:

Predictions by space and time. Here, although we only have data within clusters, we will predict for cells outside of clusters based on covariates. We will also predict for the month for whcih we do not have data.

#set_up prediction date frame
nd_m1 <- st_as_sf(mw_100m_cropped)  %>%
  mutate(centroid = st_centroid(geometry)) %>%
  mutate(x = st_coordinates(centroid)[, 1],
         y = st_coordinates(centroid)[, 2]) %>%
  select(-centroid)  %>%
  st_drop_geometry() %>%
  rename(pop_density = 1) %>%
  mutate(pop_density_km2 = pop_density / 0.01)
G1;H1;Errorh: object 'mw_100m_cropped' not found
Error during wrapup: not that many frames on the stack
Error: no more error handlers available (recursive errors?); invoking 'abort' restart
g

Now just draw 50 random coordinates, and predict by time to see whether we captured the trend.

#sample coordinate points from the household dataset
#we will fix the small number sampled later!
set.seed(123) 
sampled_points_m1 <- aq_model_data %>%
  sample_n(50) %>%
  select(x, y)

#generate DOY 0–365 and calculate Fourier terms
doy_grid <- tibble(doy = 0:365) %>%
  mutate(
    sin_doy1 = sin(2 * pi * doy / 365),
    cos_doy1 = cos(2 * pi * doy / 365),
    sin_doy2 = sin(4 * pi * doy / 365),
    cos_doy2 = cos(4 * pi * doy / 365),
    sin_doy3 = sin(6 * pi * doy / 365),
    cos_doy3 = cos(6 * pi * doy / 365)
  )

#expand grid across sampled locations
prediction_df_m1 <- sampled_points_m1 %>%
  crossing(doy_grid)

#add predictions
preds_m1 <- add_epred_draws(object = m1, newdata = prediction_df_m1)

#summarise
preds_m1_sum <- preds_m1 %>%
  ungroup() %>%
  group_by(doy) %>%
  summarise(.epred_mean = mean(.epred),
            .lower = quantile(.epred, probs=0.025),
            .upper = quantile(.epred, probs = 0.975))

#GEt the observed data
observed_data <- aq_model_data %>%
  select(mean_doy, log_pm2_5) 

#plot
preds_m1_sum %>%
  ggplot() +
  geom_ribbon(aes(x=doy, ymin=.lower, ymax = .upper), fill="steelblue", alpha=0.3) +
  geom_line(aes(x=doy, y=.epred_mean)) +
  geom_jitter(data = observed_data, aes(x = mean_doy, y = log_pm2_5),
              color = "darkred", alpha = 0.6, width = 0.5, height = 0.0, size = 1.2) +
  labs(title = "Model-estimated log(PM2.5) with empirical measurements",
       subtitle = "Model predictions with 95% CrI and observed data points",
       x = "Day of year",
       y = "log(PM2.5)",
       caption = "Modelled estimates restricted to within clusters") +
  theme_ggdist() +
  theme(panel.background = element_rect(colour = "grey78"),
        legend.position = "none")

Model 2: With covariates

Now we include grid level covariates of distance to the road, population density, and building footprint percent, along witht the mean temp and huidity on the day of measurement (from the purple air monitors)

Again, priors to be fixed later

Predictions by space and time

Sample coordinates, and plot over time


#sample coordinate points
#will sort out the small number later
set.seed(123)
sampled_points_m2 <- aq_model_data %>%
  sample_n(50) %>%
  select(x, y, mean_temp_c, mean_current_humidity, pop_density_km2, building_coverage_pct, dist_to_road_m, grid_id, log_pm2_5)

#generate DOY 0–365 and calculate Fourier terms
doy_grid <- tibble(doy = seq(0,365, by=1)) %>%
  mutate(
    sin_doy1 = sin(2 * pi * doy / 365),
    cos_doy1 = cos(2 * pi * doy / 365),
    sin_doy2 = sin(4 * pi * doy / 365),
    cos_doy2 = cos(4 * pi * doy / 365),
    sin_doy3 = sin(6 * pi * doy / 365),
    cos_doy3 = cos(6 * pi * doy / 365)
  )

#expand grid across sampled locations
prediction_df_m2 <- sampled_points_m2 %>%
  crossing(doy_grid)

#add predictions
preds_m2 <- add_epred_draws(object = m2, newdata = prediction_df_m2, ndraws = 100)

#observed data for plotting
observed_data <- aq_model_data %>%
  select(mean_doy, log_pm2_5) %>%
  mutate(mean_doy = round(mean_doy))

#plot
preds_m2 %>%
  ungroup() %>%
  ggplot(aes(x=doy)) +
  stat_lineribbon(aes(y=.epred), .width=0.95) + 
  geom_jitter(data = observed_data, aes(x = mean_doy, y = log_pm2_5),
              color = "darkred", alpha = 0.6, width = 0.5, height = 0.0, size = 1.2) +
  scale_fill_brewer() +
  labs(title = "Model-estimated log(PM2.5) with empirical measurements",
       subtitle = "Model predictions with 95% CrI and observed data points",
       x = "Day of year",
       y = "log(PM2.5)",
       caption = "Modelled estimates restricted to within clusters") +
  theme_ggdist() +
  theme(panel.background = element_rect(colour = "grey78"),
        legend.position = "none")

Compare models, using LOO CV


library(loo)

loo_m1 <- loo(m1)
loo_m2 <- loo(m2)

loo_compare(loo_m1, loo_m2)

TODO

LS0tCnRpdGxlOiAiQmxhbnR5cmUgQWlyIFF1YWxpdHkgTW9kZWxsaW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoYnJtcykKbGlicmFyeSh0aWR5YmF5ZXMpCmxpYnJhcnkoc2YpCmxpYnJhcnkobWdjdikKbGlicmFyeShwcmlvcnNlbnNlKQpsaWJyYXJ5KG9zbWRhdGEpCmxpYnJhcnkobm5nZW8pIApgYGAKCgpJbXBvcnQgdGhlIG1vZGVsbGluZyBkYXRhc2V0IC0gY2xlYW5lZCBhbmQgcHJlcHBlZCBpbiB0aGUgYDIwMjUtMDUtMTJfYXFfY2xlYW4uUm1kYCBzY3JpcHQKCmBgYHtyfQoKYXFfbW9kZWxfZGF0YSA8LSByZWFkX3JkcygiaW5wdXRfZGF0YS9hcV9tb2RlbF9kYXRhLnJkcyIpCgojYWxzbyBsb2FkIHRoZSBzY2FsZSBjbHVzdGVycwpsb2FkKCJpbnB1dF9kYXRhL3NjYWxlXzcyX2NsdXN0ZXJzLnJkYSIpICNTQ0FMRSBjbHVzdGVycwoKI2FuZCB0aGUgZ3JpZCBkYXRhCm13XzEwMG1fY3JvcHBlZCA8LSByZWFkX3JkcygiaW5wdXRfZGF0YS9td18xMDBtX2Nyb3BwZWQucmRzIikKbXdfMTAwbV9ncmlkX3NmIDwtIHJlYWRfcmRzKCJpbnB1dF9kYXRhL213XzEwMG1fZ3JpZF9zZi5yZHMiKQoKCmBgYAoKCiMjIyBNb2RlbCAxOgoKCiJXZSBmaXR0ZWQgYSBzcGF0aWFsbHkgc21vb3RoIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIGxvZy10cmFuc2Zvcm1lZCBQTTIuNSBjb25jZW50cmF0aW9ucyB1c2luZyBhIEdhdXNzaWFuIHByb2Nlc3MgKEdQKSBzbW9vdGggb3ZlciBzcGF0aWFsIGNvb3JkaW5hdGVzICh4LCB5KSB0byBjYXB0dXJlIGZsZXhpYmxlIHNwYXRpYWwgdHJlbmRzLiBTZWFzb25hbCB2YXJpYXRpb24gd2FzIG1vZGVsbGVkIHVzaW5nIGEgRm91cmllciBzZXJpZXMgZXhwYW5zaW9uIG9mIGRheS1vZi15ZWFyIHVwIHRvIHRoZSAzcmQgaGFybW9uaWMgKGkuZS4sIHNpbmUgYW5kIGNvc2luZSB0ZXJtcyBmb3IgYW5udWFsLCBzZW1pLWFubnVhbCwgYW5kIHRyaS1hbm51YWwgY3ljbGVzKSB0byBhY2NvdW50IGZvciBjb21wbGV4IHNlYXNvbmFsIHBhdHRlcm5zLiBUaGUgbW9kZWwgd2FzIGZpdHRlZCBpbiBhIEJheWVzaWFuIGZyYW1ld29yayB1c2luZyBicm1zIHdpdGggYSBHYXVzc2lhbiBsaWtlbGlob29kIGFuZCB0aGUgY21kc3RhbnIgYmFja2VuZC4iCgpOb3RlLCBwcmlvcnMgYXJlIHN0aWxsIGNhdXNpbmcgaXNzdWVzIGZvciBtZSwgc28gd2Ugd2lsbCBjb21tZW50IG91dCBub3csIGFuZCB1c2UgdGhlIGRlZmF1bHkgc3RhbiB3ZWFrbHkgaW5mb3JtYXRpdmUgcHJpb3JzCgpQcmlvcnMKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CgpwcmlvcnMgPC0gYygKICBwcmlvcihub3JtYWwoMy40LCAxKSwgY2xhc3MgPSAiSW50ZXJjZXB0IiksCiAgcHJpb3Iobm9ybWFsKDAsMSksIGNsYXNzID0gImIiKSwKICBwcmlvcihleHBvbmVudGlhbCgxKSwgY2xhc3MgPSAic2lnbWEiKSwKICBwcmlvcihleHBvbmVudGlhbCgxKSwgY2xhc3MgPSAic2RncCIpLAogIHByaW9yKG5vcm1hbCgwLCAxKSwgY2xhc3MgPSAibHNjYWxlIiwgbGIgPSAwKQopCgpgYGAKCkZpdCBwcmlvciBvbmx5IG1vZGVsCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQoKbTFfcHJpb3IgPC0gYnJtKAogICAgZm9ybXVsYSA9IGxvZ19wbTJfNSB+IGdwKHgsIHksIGs9MTUpICsKICAgICAgc2luX2RveTEgKyBjb3NfZG95MSArCiAgICAgIHNpbl9kb3kyICsgY29zX2RveTIgKwogICAgICBzaW5fZG95MyArIGNvc19kb3kzLAogICAgZGF0YSA9IGFxX21vZGVsX2RhdGEsCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpLAogICAgcHJpb3IgPSBwcmlvcnMsCiAgICBzYW1wbGVfcHJpb3IgPSAib25seSIsCiAgICBjaGFpbnMgPSA0LCBjb3JlcyA9IDQsCiAgICBiYWNrZW5kID0gImNtZHN0YW5yIgogICkKCgpzdW1tYXJ5KG0xX3ByaW9yKQpwbG90KG0xX3ByaW9yKQoKYGBgCgpOb3cgbW9kZWwgd2l0aCBkYXRhLgoKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9Cm0xIDwtIGJybSgKICAgIGZvcm11bGEgPSBsb2dfcG0yXzUgfiBncCh4LCB5LCBrPTE1KSAgKwogICAgc2luX2RveTEgKyBjb3NfZG95MSArCiAgICBzaW5fZG95MiArIGNvc19kb3kyICsKICAgIHNpbl9kb3kzICsgY29zX2RveTMsCiAgICBkYXRhID0gYXFfbW9kZWxfZGF0YSwKICAgIGZhbWlseSA9IGdhdXNzaWFuKCksCiAgICBwcmlvciA9IHByaW9ycywKICAgIGNoYWlucyA9IDQsIGNvcmVzID0gNCwKICAgIGJhY2tlbmQgPSAiY21kc3RhbnIiCiAgKQoKc3VtbWFyeShtMSkKY29uZGl0aW9uYWxfZWZmZWN0cyhtMSkKcHBfY2hlY2sobTEpCnBsb3QobTEpCgpgYGAKCkNvbXBhcmUgcHJpb3Itb25seSBtb2RlbCB0byBtb2RlbCB3aXRoIGRhdGEgdXNpbmcgYHByaW9yc2Vuc2VgIHBhY2thZ2U6CgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQoKbTFfZHJhd3MgPC0gYXNfZHJhd3NfZGYobTEpCgojIEV4dHJhY3QgcHJpb3IgYW5kIHBvc3RlcmlvciBkcmF3cwpwb3dlcnNjYWxlX3NlbnNpdGl2aXR5KG0xLCB2YXJpYWJsZSA9IGMoImJfSW50ZXJjZXB0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYl9zaW5fZG95MSIsICJiX2Nvc19kb3kxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJiX3Npbl9kb3kyIiwgImJfY29zX2RveTIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJfc2luX2RveTMiLCAiYl9jb3NfZG95MyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2RncF9ncHh5IiwgInNpZ21hIiwgIkludGVyY2VwdCIpKQoKcG93ZXJzY2FsZV9wbG90X2RlbnMobTEsIHZhcmlhYmxlID0gYygiYl9JbnRlcmNlcHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJiX3Npbl9kb3kxIiwgImJfY29zX2RveTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJfc2luX2RveTIiLCAiYl9jb3NfZG95MiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYl9zaW5fZG95MyIsICJiX2Nvc19kb3kzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzZGdwX2dweHkiLCAic2lnbWEiLCAiSW50ZXJjZXB0IikpCmBgYAoKUHJlZGljdGlvbnMgYnkgc3BhY2UgYW5kIHRpbWUuIEhlcmUsIGFsdGhvdWdoIHdlIG9ubHkgaGF2ZSBkYXRhIHdpdGhpbiBjbHVzdGVycywgd2Ugd2lsbCBwcmVkaWN0IGZvciBjZWxscyBvdXRzaWRlIG9mIGNsdXN0ZXJzIGJhc2VkIG9uIGNvdmFyaWF0ZXMuCldlIHdpbGwgYWxzbyBwcmVkaWN0IGZvciB0aGUgbW9udGggZm9yIHdoY2loIHdlIGRvIG5vdCBoYXZlIGRhdGEuCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQoKI3NldF91cCBwcmVkaWN0aW9uIGRhdGUgZnJhbWUKbmRfbTEgPC0gc3RfYXNfc2YobXdfMTAwbV9jcm9wcGVkKSAgJT4lCiAgbXV0YXRlKGNlbnRyb2lkID0gc3RfY2VudHJvaWQoZ2VvbWV0cnkpKSAlPiUKICBtdXRhdGUoeCA9IHN0X2Nvb3JkaW5hdGVzKGNlbnRyb2lkKVssIDFdLAogICAgICAgICB5ID0gc3RfY29vcmRpbmF0ZXMoY2VudHJvaWQpWywgMl0pICU+JQogIHNlbGVjdCgtY2VudHJvaWQpICAlPiUKICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lCiAgcmVuYW1lKHBvcF9kZW5zaXR5ID0gMSkgJT4lCiAgbXV0YXRlKHBvcF9kZW5zaXR5X2ttMiA9IHBvcF9kZW5zaXR5IC8gMC4wMSkKCiNnZXQgdGhlIGZpcnN0IGRheSBvZiBlYWNoIG1vbnRoIGZvciBwcmVkaWN0aW9uCmZpcnN0X2RheXMgPC0geW1kKHBhc3RlMCgiMjAyMC0iLCBzcHJpbnRmKCIlMDJkIiwgMToxMiksICItMDEiKSkKZmlyc3RfZGF5X2RveSA8LSB5ZGF5KGZpcnN0X2RheXMpCgojY2FsY3VsYXRlIEZvdXJpZXIgdGVybXMKZmlyc3RfZGF5X3NlYXNvbmFsaXR5IDwtIHRpYmJsZSgKICBtZWFuX2RveSA9IGZpcnN0X2RheV9kb3ksCiAgc2luX2RveTEgPSBzaW4oMiAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIGNvc19kb3kxID0gY29zKDIgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBzaW5fZG95MiA9IHNpbig0ICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgY29zX2RveTIgPSBjb3MoNCAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIHNpbl9kb3kzID0gc2luKDYgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBjb3NfZG95MyA9IGNvcyg2ICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgZGF0ZSA9IGZpcnN0X2RheXMKKQoKI2V4cGFuZCBncmlkIGZvciBwcmVkaWN0aW9uCm5kX20xIDwtIG5kX20xICU+JQogIGNyb3NzaW5nKGZpcnN0X2RheV9zZWFzb25hbGl0eSkKCiN0YWtlIHBvc3RlcmlvciBkcmF3cyAtIG5vdGUgc3RvcmluZyBhcyBhbiBydmFycyBvYmplY3QgZm9yIGVmZmljaWVuY3kKI25vdGUgY2FuIG9ubHkgbWFuYWdlIHRoaXMgd2l0aG91dCBjcmFzaGluZyBjb21wdXRlciEKI3RvIGFkZHJlc3MgbGF0ZXIsIGFuZCBpbXByb3ZlIGVmZmljaWVueSBmb3IgbW9yZSBkcmF3cwptMV9kcmF3cyA8LSBhZGRfZXByZWRfcnZhcnMob2JqZWN0ID0gbTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gbmRfbTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZHJhd3MgPSA1MDApIAoKI25vdyBleHRyYWN0IHRoZSBzdW1tYXJ5IG1lYW4gYW5kIHNkIGZvciBlYWNoIG1vbnRoLWdyaWQgY2VsbCBjb21iaW5hdGlvbgptMV9lcHJlZF9hcnJheSA8LSBwb3N0ZXJpb3I6OmRyYXdzX29mKG0xX2RyYXdzJC5lcHJlZCkKCiNjb21wdXRlIHBvc3RlcmlvciBtZWFucyBwZXIgbG9jYXRpb24KbTFfZHJhd3MkLmVwcmVkX21lYW4gPC0gY29sTWVhbnMobTFfZXByZWRfYXJyYXkpCgojY29tcHV0ZSBwb3N0ZXJpb3Igc2RzIHBlciBsb2NhdGlvbgptMV9kcmF3cyQuZXByZWRfc2QgPC0gYXBwbHkobTFfZXByZWRfYXJyYXksIDIsIHNkKQoKbTFfc3VtIDwtIG0xX2RyYXdzICU+JSAKICBzZWxlY3QoeCwgeSwgZGF0ZSwgLmVwcmVkX21lYW4sIC5lcHJlZF9zZCkKCgojcGxvdCBwcmVkaWN0aW9ucwptMV9zdW0gJT4lICAKICBtdXRhdGUoZGF0ZSA9IG1vbnRoKGRhdGUsIGxhYmVsPVRSVUUpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV90aWxlKGFlcyh4ID0geCwgeT15LCBmaWxsPS5lcHJlZF9tZWFuKSkgKwogIGdlb21fc2YoZGF0YSA9IHNjYWxlXzcyX2NsdXN0ZXJzLCBjb2xvdXI9ImdyZXk3OCIsIGZpbGw9TkEpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfYygpICsKICBmYWNldF93cmFwKGRhdGV+LikgKwogIGxhYnModGl0bGUgPSAiTG9nKFBNMi41KSBleHBvc3VyZSIsCiAgICAgICB4PSIiLAogICAgICAgeT0iIikgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9TkEsIGNvbG91cj0iZ3JleTc4IiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleTc4IikpCgpgYGAKCk5vdyBqdXN0IGRyYXcgNTAgcmFuZG9tIGNvb3JkaW5hdGVzLCBhbmQgcHJlZGljdCBieSB0aW1lIHRvIHNlZSB3aGV0aGVyIHdlIGNhcHR1cmVkIHRoZSB0cmVuZC4KCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CiNzYW1wbGUgY29vcmRpbmF0ZSBwb2ludHMgZnJvbSB0aGUgaG91c2Vob2xkIGRhdGFzZXQKI3dlIHdpbGwgZml4IHRoZSBzbWFsbCBudW1iZXIgc2FtcGxlZCBsYXRlciEKc2V0LnNlZWQoMTIzKSAKc2FtcGxlZF9wb2ludHNfbTEgPC0gYXFfbW9kZWxfZGF0YSAlPiUKICBzYW1wbGVfbig1MCkgJT4lCiAgc2VsZWN0KHgsIHkpCgojZ2VuZXJhdGUgRE9ZIDDigJMzNjUgYW5kIGNhbGN1bGF0ZSBGb3VyaWVyIHRlcm1zCmRveV9ncmlkIDwtIHRpYmJsZShkb3kgPSAwOjM2NSkgJT4lCiAgbXV0YXRlKAogICAgc2luX2RveTEgPSBzaW4oMiAqIHBpICogZG95IC8gMzY1KSwKICAgIGNvc19kb3kxID0gY29zKDIgKiBwaSAqIGRveSAvIDM2NSksCiAgICBzaW5fZG95MiA9IHNpbig0ICogcGkgKiBkb3kgLyAzNjUpLAogICAgY29zX2RveTIgPSBjb3MoNCAqIHBpICogZG95IC8gMzY1KSwKICAgIHNpbl9kb3kzID0gc2luKDYgKiBwaSAqIGRveSAvIDM2NSksCiAgICBjb3NfZG95MyA9IGNvcyg2ICogcGkgKiBkb3kgLyAzNjUpCiAgKQoKI2V4cGFuZCBncmlkIGFjcm9zcyBzYW1wbGVkIGxvY2F0aW9ucwpwcmVkaWN0aW9uX2RmX20xIDwtIHNhbXBsZWRfcG9pbnRzX20xICU+JQogIGNyb3NzaW5nKGRveV9ncmlkKQoKI2FkZCBwcmVkaWN0aW9ucwpwcmVkc19tMSA8LSBhZGRfZXByZWRfZHJhd3Mob2JqZWN0ID0gbTEsIG5ld2RhdGEgPSBwcmVkaWN0aW9uX2RmX20xKQoKI3N1bW1hcmlzZQpwcmVkc19tMV9zdW0gPC0gcHJlZHNfbTEgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KGRveSkgJT4lCiAgc3VtbWFyaXNlKC5lcHJlZF9tZWFuID0gbWVhbiguZXByZWQpLAogICAgICAgICAgICAubG93ZXIgPSBxdWFudGlsZSguZXByZWQsIHByb2JzPTAuMDI1KSwKICAgICAgICAgICAgLnVwcGVyID0gcXVhbnRpbGUoLmVwcmVkLCBwcm9icyA9IDAuOTc1KSkKCiNHRXQgdGhlIG9ic2VydmVkIGRhdGEKb2JzZXJ2ZWRfZGF0YSA8LSBhcV9tb2RlbF9kYXRhICU+JQogIHNlbGVjdChtZWFuX2RveSwgbG9nX3BtMl81KSAKCiNwbG90CnByZWRzX20xX3N1bSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yaWJib24oYWVzKHg9ZG95LCB5bWluPS5sb3dlciwgeW1heCA9IC51cHBlciksIGZpbGw9InN0ZWVsYmx1ZSIsIGFscGhhPTAuMykgKwogIGdlb21fbGluZShhZXMoeD1kb3ksIHk9LmVwcmVkX21lYW4pKSArCiAgZ2VvbV9qaXR0ZXIoZGF0YSA9IG9ic2VydmVkX2RhdGEsIGFlcyh4ID0gbWVhbl9kb3ksIHkgPSBsb2dfcG0yXzUpLAogICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBhbHBoYSA9IDAuNiwgd2lkdGggPSAwLjUsIGhlaWdodCA9IDAuMCwgc2l6ZSA9IDEuMikgKwogIGxhYnModGl0bGUgPSAiTW9kZWwtZXN0aW1hdGVkIGxvZyhQTTIuNSkgd2l0aCBlbXBpcmljYWwgbWVhc3VyZW1lbnRzIiwKICAgICAgIHN1YnRpdGxlID0gIk1vZGVsIHByZWRpY3Rpb25zIHdpdGggOTUlIENySSBhbmQgb2JzZXJ2ZWQgZGF0YSBwb2ludHMiLAogICAgICAgeCA9ICJEYXkgb2YgeWVhciIsCiAgICAgICB5ID0gImxvZyhQTTIuNSkiLAogICAgICAgY2FwdGlvbiA9ICJNb2RlbGxlZCBlc3RpbWF0ZXMgcmVzdHJpY3RlZCB0byB3aXRoaW4gY2x1c3RlcnMiKSArCiAgdGhlbWVfZ2dkaXN0KCkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXk3OCIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYAoKIyMjIE1vZGVsIDI6IFdpdGggY292YXJpYXRlcwoKTm93IHdlIGluY2x1ZGUgZ3JpZCBsZXZlbCBjb3ZhcmlhdGVzIG9mIGRpc3RhbmNlIHRvIHRoZSByb2FkLCBwb3B1bGF0aW9uIGRlbnNpdHksIGFuZCBidWlsZGluZyBmb290cHJpbnQgcGVyY2VudCwgYWxvbmcgd2l0aHQgdGhlIG1lYW4gdGVtcCBhbmQgaHVpZGl0eSBvbiB0aGUgZGF5IG9mIG1lYXN1cmVtZW50IChmcm9tIHRoZSBwdXJwbGUgYWlyIG1vbml0b3JzKQoKQWdhaW4sIHByaW9ycyB0byBiZSBmaXhlZCBsYXRlcgoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KcHJpb3JzIDwtIGMoCiAgcHJpb3Iobm9ybWFsKDMuNCwgMSksIGNsYXNzID0gIkludGVyY2VwdCIpLAogIHByaW9yKG5vcm1hbCgwLDEpLCBjbGFzcyA9ICJiIiksCiAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gInNpZ21hIiksCiAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gInNkZ3AiKSwKICBwcmlvcihub3JtYWwoMCwgMSksIGNsYXNzID0gImxzY2FsZSIsIGxiID0gMCkKKQoKCm0yIDwtIGJybSgKICAgIGZvcm11bGEgPSBsb2dfcG0yXzUgfiBncCh4LCB5LCBrPTE1KSAgKwogICAgICBzKG1lYW5fdGVtcF9jLCBrPTUpICsgCiAgICAgIHMobWVhbl9jdXJyZW50X2h1bWlkaXR5LCBrPTUpICsKICAgICAgcyhwb3BfZGVuc2l0eV9rbTIsIGs9NSkgKwogICAgICBzKGJ1aWxkaW5nX2NvdmVyYWdlX3BjdCwgaz01KSArCiAgICAgIHMoZGlzdF90b19yb2FkX20sIGs9NSkgKwogICAgICBzaW5fZG95MSArIGNvc19kb3kxICsKICAgICAgc2luX2RveTIgKyBjb3NfZG95MiArCiAgICAgIHNpbl9kb3kzICsgY29zX2RveTMsCiAgICBkYXRhID0gYXFfbW9kZWxfZGF0YSwKICAgIGZhbWlseSA9IGdhdXNzaWFuKCksCiAgICBwcmlvciA9IHByaW9ycywKICAgIGNoYWlucyA9IDQsIGNvcmVzID0gNCwKICAgIGJhY2tlbmQgPSAiY21kc3RhbnIiCiAgKQoKc3VtbWFyeShtMikKY29uZGl0aW9uYWxfZWZmZWN0cyhtMikKcHBfY2hlY2sobTIpCnBsb3QobTIpCgoKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQoKbTJfZHJhd3MgPC0gYXNfZHJhd3NfZGYobTIpCgojIEV4dHJhY3QgcHJpb3IgYW5kIHBvc3RlcmlvciBkcmF3cwpwb3dlcnNjYWxlX3NlbnNpdGl2aXR5KG0yLCB2YXJpYWJsZSA9IGMoImJfSW50ZXJjZXB0IiwgImJfc2luX2RveTEiLCAiYl9jb3NfZG95MSIsICJiX3Npbl9kb3kyIiwgImJfY29zX2RveTIiLCAiYl9zaW5fZG95MyIsICJiX2Nvc19kb3kzIiwgImJzX3NtZWFuX3RlbXBfY18xIiwgImJzX3NtZWFuX2N1cnJlbnRfaHVtaWRpdHlfMSIsICJic19zcG9wX2RlbnNpdHlfa20yXzEiLCAiYnNfc2J1aWxkaW5nX2NvdmVyYWdlX3BjdF8xIiwgImJzX3NkaXN0X3RvX3JvYWRfbV8xIiwgICAgICAgICAKInNkc19zbWVhbl90ZW1wX2NfMSIsICJzZHNfc21lYW5fY3VycmVudF9odW1pZGl0eV8xIiwgInNkc19zcG9wX2RlbnNpdHlfa20yXzEiLCAic2RzX3NidWlsZGluZ19jb3ZlcmFnZV9wY3RfMSIsIAoic2RzX3NkaXN0X3RvX3JvYWRfbV8xIiwgInNkZ3BfZ3B4eSIsICJsc2NhbGVfZ3B4eSIsICJzaWdtYSIsICJJbnRlcmNlcHQiLCAic19zbWVhbl90ZW1wX2NfMVsxXSIsICJzX3NtZWFuX3RlbXBfY18xWzJdIiwgInNfc21lYW5fdGVtcF9jXzFbM10iLCAgICAgICAgICJzX3NtZWFuX2N1cnJlbnRfaHVtaWRpdHlfMVsxXSIsICAic19zbWVhbl9jdXJyZW50X2h1bWlkaXR5XzFbMl0iLCAgInNfc21lYW5fY3VycmVudF9odW1pZGl0eV8xWzNdIiwgICJzX3Nwb3BfZGVuc2l0eV9rbTJfMVsxXSIsICAgICAgIAogInNfc3BvcF9kZW5zaXR5X2ttMl8xWzJdIiwgICAgICAgICJzX3Nwb3BfZGVuc2l0eV9rbTJfMVszXSIsICAgICAgICAic19zYnVpbGRpbmdfY292ZXJhZ2VfcGN0XzFbMV0iLCAgInNfc2J1aWxkaW5nX2NvdmVyYWdlX3BjdF8xWzJdIiwgCiAic19zYnVpbGRpbmdfY292ZXJhZ2VfcGN0XzFbM10iLCAgInNfc2Rpc3RfdG9fcm9hZF9tXzFbMV0iLCAic19zZGlzdF90b19yb2FkX21fMVsyXSIsICJzX3NkaXN0X3RvX3JvYWRfbV8xWzNdIikpCgpwb3dlcnNjYWxlX3Bsb3RfZGVucyhtMiwgdmFyaWFibGUgPSBjKCJiX0ludGVyY2VwdCIsICJiX3Npbl9kb3kxIiwgImJfY29zX2RveTEiLCAiYl9zaW5fZG95MiIsICJiX2Nvc19kb3kyIiwgImJfc2luX2RveTMiLCAiYl9jb3NfZG95MyIsICJic19zbWVhbl90ZW1wX2NfMSIsICJic19zbWVhbl9jdXJyZW50X2h1bWlkaXR5XzEiLCAiYnNfc3BvcF9kZW5zaXR5X2ttMl8xIiwgImJzX3NidWlsZGluZ19jb3ZlcmFnZV9wY3RfMSIsICJic19zZGlzdF90b19yb2FkX21fMSIsICAgICAgICAgCiJzZHNfc21lYW5fdGVtcF9jXzEiLCAic2RzX3NtZWFuX2N1cnJlbnRfaHVtaWRpdHlfMSIsICJzZHNfc3BvcF9kZW5zaXR5X2ttMl8xIiwgInNkc19zYnVpbGRpbmdfY292ZXJhZ2VfcGN0XzEiLCAKInNkc19zZGlzdF90b19yb2FkX21fMSIsICJzZGdwX2dweHkiLCAibHNjYWxlX2dweHkiLCAic2lnbWEiLCAiSW50ZXJjZXB0IiwgInNfc21lYW5fdGVtcF9jXzFbMV0iLCAic19zbWVhbl90ZW1wX2NfMVsyXSIsICJzX3NtZWFuX3RlbXBfY18xWzNdIiwgICAgICAgICAic19zbWVhbl9jdXJyZW50X2h1bWlkaXR5XzFbMV0iLCAgInNfc21lYW5fY3VycmVudF9odW1pZGl0eV8xWzJdIiwgICJzX3NtZWFuX2N1cnJlbnRfaHVtaWRpdHlfMVszXSIsICAic19zcG9wX2RlbnNpdHlfa20yXzFbMV0iLCAgICAgICAKICJzX3Nwb3BfZGVuc2l0eV9rbTJfMVsyXSIsICAgICAgICAic19zcG9wX2RlbnNpdHlfa20yXzFbM10iLCAgICAgICAgInNfc2J1aWxkaW5nX2NvdmVyYWdlX3BjdF8xWzFdIiwgICJzX3NidWlsZGluZ19jb3ZlcmFnZV9wY3RfMVsyXSIsIAogInNfc2J1aWxkaW5nX2NvdmVyYWdlX3BjdF8xWzNdIiwgICJzX3NkaXN0X3RvX3JvYWRfbV8xWzFdIiwgInNfc2Rpc3RfdG9fcm9hZF9tXzFbMl0iLCAic19zZGlzdF90b19yb2FkX21fMVszXSIpKQpgYGAKClByZWRpY3Rpb25zIGJ5IHNwYWNlIGFuZCB0aW1lCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQoKI2ZpcnN0IHdlIG5lZWQgYSBwcmVkaWN0aW9uIGRhdGFmcmFtZSB3aXRoIGFsbCBvZiB0aGUgY292YXJpYXRlIGRhdGEKCiNleHRyYWN0IG1vbnRoIGZyb20gZGF0ZSB2YXJpYWJsZQphcV9tb2RlbF9kYXRhIDwtIGFxX21vZGVsX2RhdGEgICU+JQogIG11dGF0ZShtb250aCA9IGx1YnJpZGF0ZTo6bW9udGgoYXMuRGF0ZShtZWFuX2RveSwgb3JpZ2luID0gIjIwMTktMTItMzEiKSkpCgojY2FsY3VsYXRlIG1vbnRobHkgbWVhbnMKbW9udGhseV9tZWFucyA8LSBhcV9tb2RlbF9kYXRhICU+JQogIGdyb3VwX2J5KG1vbnRoKSAlPiUKICBzdW1tYXJpc2UoCiAgICBtZWFuX3RlbXBfYyA9IG1lYW4obWVhbl90ZW1wX2MsIG5hLnJtID0gVFJVRSksCiAgICBtZWFuX2N1cnJlbnRfaHVtaWRpdHkgPSBtZWFuKG1lYW5fY3VycmVudF9odW1pZGl0eSwgbmEucm0gPSBUUlVFKQogICkKCiNObyBkYXRhIGNvbGxlY3Rpb24gaW4gQXByaWwgLSBoZXJlIHdlIHdpbGwganVzdCBpbnRlcnBvbGF0ZQojY2FuIGRvIGJldHRlciBsYXRlci4uLgptYXJjaF90ZW1wIDwtIG1vbnRobHlfbWVhbnMgJT4lIGZpbHRlcihtb250aCA9PSAzKSAlPiUgcHVsbChtZWFuX3RlbXBfYykKbWF5X3RlbXAgPC0gbW9udGhseV9tZWFucyAlPiUgZmlsdGVyKG1vbnRoID09IDUpICU+JSBwdWxsKG1lYW5fdGVtcF9jKQphcHJpbF90ZW1wIDwtIChtYXJjaF90ZW1wICsgbWF5X3RlbXApIC8gMgoKbWFyY2hfaHVtaWRpdHkgPC0gbW9udGhseV9tZWFucyAlPiUgZmlsdGVyKG1vbnRoID09IDMpICU+JSBwdWxsKG1lYW5fY3VycmVudF9odW1pZGl0eSkKbWF5X2h1bWlkaXR5IDwtIG1vbnRobHlfbWVhbnMgJT4lIGZpbHRlcihtb250aCA9PSA1KSAlPiUgcHVsbChtZWFuX2N1cnJlbnRfaHVtaWRpdHkpCmFwcmlsX2h1bWlkaXR5IDwtIChtYXJjaF9odW1pZGl0eSArIG1heV9odW1pZGl0eSkgLyAyCgojYWRkIHRoZXNlIGludG8gdGhlIHByZWRpY3Rpb24gZGF0YWZyYW1lCm1vbnRobHlfbWVhbnMgPC0gbW9udGhseV9tZWFucyAlPiUKICBhZGRfcm93KG1vbnRoPTQsIAogICAgICAgICAgbWVhbl90ZW1wX2MgPSBhcHJpbF90ZW1wLAogICAgICAgICAgbWVhbl9jdXJyZW50X2h1bWlkaXR5ID0gYXByaWxfaHVtaWRpdHkpICU+JQogIGFycmFuZ2UobW9udGgpCgojc2V0X3VwIHByZWRpY3Rpb24gZGF0ZSBmcmFtZQpuZF9tMiA8LSBtd18xMDBtX2dyaWRfc2YgJT4lCiAgc2Y6OnN0X3NmKCkgJT4lCiAgbXV0YXRlKHggPSBzdF9jb29yZGluYXRlcyhzdF9jZW50cm9pZCguKSlbLCAxXSwKICAgICAgICAgeSA9IHN0X2Nvb3JkaW5hdGVzKHN0X2NlbnRyb2lkKC4pKVssIDJdKSAlPiUKICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lCiAgcmVuYW1lKHBvcF9kZW5zaXR5ID0gMSkgJT4lCiAgbXV0YXRlKHBvcF9kZW5zaXR5X2ttMiA9IHBvcF9kZW5zaXR5IC8gMC4wMSkKCiNnZXQgdGhlIGZpcnN0IGRheSBvZiBlYWNoIG1vbnRoIGZvciBwcmVkaWN0aW9uCmZpcnN0X2RheXMgPC0geW1kKHBhc3RlMCgiMjAyMC0iLCBzcHJpbnRmKCIlMDJkIiwgMToxMiksICItMDEiKSkKZmlyc3RfZGF5X2RveSA8LSB5ZGF5KGZpcnN0X2RheXMpCgojY2FsY3VsYXRlIEZvdXJpZXIgdGVybXMKZmlyc3RfZGF5X3NlYXNvbmFsaXR5IDwtIHRpYmJsZSgKICBtZWFuX2RveSA9IGZpcnN0X2RheV9kb3ksCiAgc2luX2RveTEgPSBzaW4oMiAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIGNvc19kb3kxID0gY29zKDIgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBzaW5fZG95MiA9IHNpbig0ICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgY29zX2RveTIgPSBjb3MoNCAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIHNpbl9kb3kzID0gc2luKDYgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBjb3NfZG95MyA9IGNvcyg2ICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgZGF0ZSA9IGZpcnN0X2RheXMKKSAlPiUKICBtdXRhdGUobW9udGggPSBsdWJyaWRhdGU6Om1vbnRoKGFzLkRhdGUobWVhbl9kb3ksIG9yaWdpbiA9ICIyMDE5LTEyLTMxIikpKSAlPiUKICBsZWZ0X2pvaW4obW9udGhseV9tZWFucykKCm5kX20yIDwtIG5kX20yICU+JQogIGNyb3NzaW5nKGZpcnN0X2RheV9zZWFzb25hbGl0eSkgJT4lCiAgbXV0YXRlKGJ1aWxkaW5nX2NvdmVyYWdlX3BjdCA9IGJ1aWxkaW5nX2NvdmVyYWdlX3BjdC8xMDApCgojdGFrZSBwb3N0ZXJpb3IgZHJhd3MgLSBub3RlIHN0b3JpbmcgYXMgYW4gcnZhcnMgb2JqZWN0IGZvciBlZmZpY2llbmN5Cm0yX2RyYXdzIDwtIGFkZF9lcHJlZF9ydmFycyhvYmplY3QgPSBtMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBuZF9tMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5kcmF3cyA9IDIwMCkgI25vdGUgY2FuIG9ubHkgbWFuYWdlIHRoaXMgd2l0aG91dCBjcmFzaGluZyBjb21wdXRlciEKCiNub3cgZXh0cmFjdCB0aGUgc3VtbWFyeSBtZWFuIGFuZCBzZCBmb3IgZWFjaCBtb250aC1ncmlkIGNlbGwgY29tYmluYXRpb24KbTJfZXByZWRfYXJyYXkgPC0gcG9zdGVyaW9yOjpkcmF3c19vZihtMl9kcmF3cyQuZXByZWQpCgojY29tcHV0ZSBwb3N0ZXJpb3IgbWVhbnMgcGVyIGxvY2F0aW9uCm0yX2RyYXdzJC5lcHJlZF9tZWFuIDwtIGNvbE1lYW5zKG0yX2VwcmVkX2FycmF5KQoKI2NvbXB1dGUgcG9zdGVyaW9yIHNkIHBlciBsb2NhdGlvbgptMl9kcmF3cyQuZXByZWRfc2QgPC0gYXBwbHkobTJfZXByZWRfYXJyYXksIDIsIHNkKQoKbTJfc3VtIDwtIG0yX2RyYXdzICU+JSAKICBzZWxlY3QoeCwgeSwgZGF0ZSwgLmVwcmVkX21lYW4sIC5lcHJlZF9zZCkKCgojcGxvdCBwcmVkaWN0aW9ucwptMl9zdW0gJT4lICAKICBtdXRhdGUoZGF0ZSA9IG1vbnRoKGRhdGUsIGxhYmVsID0gVFJVRSkpICU+JQogIG11dGF0ZSguZXByZWRfbWVhbiA9IGV4cCguZXByZWRfbWVhbikpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3RpbGUoYWVzKHggPSB4LCB5PXksIGZpbGw9LmVwcmVkX21lYW4pKSArCiAgZ2VvbV9zZihkYXRhID0gc2NhbGVfNzJfY2x1c3RlcnMsIGNvbG91cj0iZ3JleTc4IiwgZmlsbD1OQSkgKwogICNnZW9tX3NmKGRhdGEgPSBtYWluX3JvYWRzX2Nyb3BwZWQsIGNvbG91cj0id2hpdGUiKSArICNyb2FkcyBsb29raW5nIGEgYml0IG1lc3N5IHdoZW4gcGxvdHRlZCAtIHdvcmsgb24gdGhpcy4KICBzY2FsZV9maWxsX3NjaWNvKHBhbGV0dGUgPSAiYWN0b24iLAogICAgdHJhbnMgPSBzY2FsZXM6OmxvZ190cmFucyhiYXNlID0gMTApLCBuYW1lID0gIlByZWRpY3RlZFxuUE0yLjUiKSArCiAgZmFjZXRfd3JhcChkYXRlfi4pICsKICBsYWJzKHRpdGxlID0gIkxvZyhQTTIuNSkgZXhwb3N1cmUiLAogICAgICAgeD0iIiwKICAgICAgIHk9IiIsCiAgICAgICBjYXB0aW9uID0gIldoaXRlIGJvdW5kYXJpZXMgYXJlIFNDQUxFIHN0dWR5IGNsdXN0ZXJzIikgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9TkEsIGNvbG91cj0iZ3JleTc4IiksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleTc4IiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKI3Bsb3Qgc2QKbTJfc3VtICU+JSAgCiAgbXV0YXRlKGRhdGUgPSBtb250aChkYXRlLCBsYWJlbCA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV90aWxlKGFlcyh4ID0geCwgeT15LCBmaWxsPS5lcHJlZF9zZCkpICsKICBnZW9tX3NmKGRhdGEgPSBzY2FsZV83Ml9jbHVzdGVycywgY29sb3VyPSJncmV5NzgiLCBmaWxsPU5BKSArCiAgI2dlb21fc2YoZGF0YSA9IG1haW5fcm9hZHNfY3JvcHBlZCwgY29sb3VyPSJ3aGl0ZSIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb24gPSAiRiIpICsKICBmYWNldF93cmFwKGRhdGV+LikgKwogIGxhYnModGl0bGUgPSAiTG9nKFBNMi41KSBleHBvc3VyZSIsCiAgICAgICB4PSIiLAogICAgICAgeT0iIiwKICAgICAgIGNhcHRpb24gPSAiV2hpdGUgYm91bmRhcmllcyBhcmUgU0NBTEUgc3R1ZHkgY2x1c3RlcnMiKSArCiAgdGhlbWVfZ2dkaXN0KCkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD1OQSwgY29sb3VyPSJncmV5NzgiKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5NzgiKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MSkpCgpgYGAKClNhbXBsZSBjb29yZGluYXRlcywgYW5kIHBsb3Qgb3ZlciB0aW1lCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQoKI3NhbXBsZSBjb29yZGluYXRlIHBvaW50cwojd2lsbCBzb3J0IG91dCB0aGUgc21hbGwgbnVtYmVyIGxhdGVyCnNldC5zZWVkKDEyMykKc2FtcGxlZF9wb2ludHNfbTIgPC0gYXFfbW9kZWxfZGF0YSAlPiUKICBzYW1wbGVfbig1MCkgJT4lCiAgc2VsZWN0KHgsIHksIG1lYW5fdGVtcF9jLCBtZWFuX2N1cnJlbnRfaHVtaWRpdHksIHBvcF9kZW5zaXR5X2ttMiwgYnVpbGRpbmdfY292ZXJhZ2VfcGN0LCBkaXN0X3RvX3JvYWRfbSwgZ3JpZF9pZCwgbG9nX3BtMl81KQoKI2dlbmVyYXRlIERPWSAw4oCTMzY1IGFuZCBjYWxjdWxhdGUgRm91cmllciB0ZXJtcwpkb3lfZ3JpZCA8LSB0aWJibGUoZG95ID0gc2VxKDAsMzY1LCBieT0xKSkgJT4lCiAgbXV0YXRlKAogICAgc2luX2RveTEgPSBzaW4oMiAqIHBpICogZG95IC8gMzY1KSwKICAgIGNvc19kb3kxID0gY29zKDIgKiBwaSAqIGRveSAvIDM2NSksCiAgICBzaW5fZG95MiA9IHNpbig0ICogcGkgKiBkb3kgLyAzNjUpLAogICAgY29zX2RveTIgPSBjb3MoNCAqIHBpICogZG95IC8gMzY1KSwKICAgIHNpbl9kb3kzID0gc2luKDYgKiBwaSAqIGRveSAvIDM2NSksCiAgICBjb3NfZG95MyA9IGNvcyg2ICogcGkgKiBkb3kgLyAzNjUpCiAgKQoKI2V4cGFuZCBncmlkIGFjcm9zcyBzYW1wbGVkIGxvY2F0aW9ucwpwcmVkaWN0aW9uX2RmX20yIDwtIHNhbXBsZWRfcG9pbnRzX20yICU+JQogIGNyb3NzaW5nKGRveV9ncmlkKQoKI2FkZCBwcmVkaWN0aW9ucwpwcmVkc19tMiA8LSBhZGRfZXByZWRfZHJhd3Mob2JqZWN0ID0gbTIsIG5ld2RhdGEgPSBwcmVkaWN0aW9uX2RmX20yLCBuZHJhd3MgPSAxMDApCgojb2JzZXJ2ZWQgZGF0YSBmb3IgcGxvdHRpbmcKb2JzZXJ2ZWRfZGF0YSA8LSBhcV9tb2RlbF9kYXRhICU+JQogIHNlbGVjdChtZWFuX2RveSwgbG9nX3BtMl81KSAlPiUKICBtdXRhdGUobWVhbl9kb3kgPSByb3VuZChtZWFuX2RveSkpCgojcGxvdApwcmVkc19tMiAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh4PWRveSkpICsKICBzdGF0X2xpbmVyaWJib24oYWVzKHk9LmVwcmVkKSwgLndpZHRoPTAuOTUpICsgCiAgZ2VvbV9qaXR0ZXIoZGF0YSA9IG9ic2VydmVkX2RhdGEsIGFlcyh4ID0gbWVhbl9kb3ksIHkgPSBsb2dfcG0yXzUpLAogICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBhbHBoYSA9IDAuNiwgd2lkdGggPSAwLjUsIGhlaWdodCA9IDAuMCwgc2l6ZSA9IDEuMikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKCkgKwogIGxhYnModGl0bGUgPSAiTW9kZWwtZXN0aW1hdGVkIGxvZyhQTTIuNSkgd2l0aCBlbXBpcmljYWwgbWVhc3VyZW1lbnRzIiwKICAgICAgIHN1YnRpdGxlID0gIk1vZGVsIHByZWRpY3Rpb25zIHdpdGggOTUlIENySSBhbmQgb2JzZXJ2ZWQgZGF0YSBwb2ludHMiLAogICAgICAgeCA9ICJEYXkgb2YgeWVhciIsCiAgICAgICB5ID0gImxvZyhQTTIuNSkiLAogICAgICAgY2FwdGlvbiA9ICJNb2RlbGxlZCBlc3RpbWF0ZXMgcmVzdHJpY3RlZCB0byB3aXRoaW4gY2x1c3RlcnMiKSArCiAgdGhlbWVfZ2dkaXN0KCkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXk3OCIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCgoKYGBgCgoKQ29tcGFyZSBtb2RlbHMsIHVzaW5nIExPTyBDVgoKYGBge3J9CgpsaWJyYXJ5KGxvbykKCmxvb19tMSA8LSBsb28obTEpCmxvb19tMiA8LSBsb28obTIpCgpsb29fY29tcGFyZShsb29fbTEsIGxvb19tMikKYGBgCgoKVE9ETwoKIC0gT1RIRVIgT1VUQ09NRSBNRUFTVVJFUyAoUE0xLCBQTTEwLCBOTykKIC0gQ0FOIFdFIExJTksgVE8gVEhFIFNUQVRJQyBBUSBNT05JVE9SUyAoT1VURE9PUlMpCiAtIFBSSU9SUwogLSBPVEhFUiBDT1ZBUklBVEVTCiAtIENPTVBBUkUgTU9ERUxTIFdJVEggRElGRkVSRU5UIEJBU0lTIEZVTkNUSU9OUyBGT1IgR1AgQU5EIFNQTElORVMKIC0gRVhDRUVEQU5DRVMKIC0gTElOSyBUTyBNVEIgSU5GRUNUSU9OIFBSRVZBTEVOQ0UgREFUQSwgQU5EIE1PREVMCg==